package com.youlu.campus.service.activity.impl;

import com.alibaba.fastjson.JSON;
import com.youlu.campus.base.exception.BusinessException;

import com.youlu.campus.entity.ActivityInfo;
import com.youlu.campus.entity.ActivitySimulationData;
import com.youlu.campus.entity.ActivityStatistics;
import com.youlu.campus.entity.VO.req.ActivityStatisticsQueryVO;
import com.youlu.campus.entity.system.UserDataPermission;
import com.youlu.campus.service.activity.*;
import com.youlu.campus.service.platform.PlatformConfigService;
import com.youlu.campus.service.system.UserDataPermissionService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service
public class ActivityStatisticsServiceImpl implements ActivityStatisticsService {
    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private ActivityCostStatisticsService activityCostStatisticsService;
    @Autowired
    private ActivityService activityService;
    @Autowired
    private UserParticipateActivityInfoService userParticipateActivityInfoService;
    @Autowired
    private UserDataPermissionService userDataPermissionService;
    @Autowired
    private PlatformConfigService platformConfigService;
    @Lazy
    @Autowired
    private ActivitySimulationDataService activitySimulationDataService;

    @Override
    public Page<ActivityStatistics> list(ActivityStatisticsQueryVO request) {
        log.info(":>>> 开始获取活动任务列表:{}", JSON.toJSON(request));
        if (Objects.isNull(request)) {
            log.error(":>>> 活动任务参数错误:活动ID不能为空");
            throw new BusinessException("活动ID不能为空");
        }
        Query query = new Query();
        List<String> activityIds = new ArrayList<>();
        UserDataPermission userDataPermission = null;
        if (StringUtils.isNotBlank(request.getUserId())) {
            UserDataPermission req = new UserDataPermission();
            req.setUserId(request.getUserId());
            List<UserDataPermission> datas = userDataPermissionService.list(req);
            if (!CollectionUtils.isEmpty(datas) && !CollectionUtils.isEmpty(datas.get(0).getActivityId())) {
                userDataPermission = datas.get(0);
                log.info(":>>> 用户:{} 的数据权限权限配置:{}", request.getUserId(), JSON.toJSON(userDataPermission.getActivityId()));
                activityIds = datas.get(0).getActivityId();
//                query.addCriteria(Criteria.where("id").in(datas.get(0).getActivityId()));
            } else {
//                query.addCriteria(Criteria.where("id").in(new ArrayList<>()));
            }
        }
        log.info(":>>> 用户活动集合大小:{}", activityIds.size());
        if (StringUtils.isNotBlank(request.getActivityId())) {
            if (activityIds.contains(request.getActivityId())) {
                query.addCriteria(Criteria.where("activityId").is(request.getActivityId()));
            } else {
                query.addCriteria(Criteria.where("activityId").is("0"));
            }

        } else {
            if (!CollectionUtils.isEmpty(activityIds)) {
                query.addCriteria(Criteria.where("activityId").in(activityIds));
            } else {
                activityIds.add("0");
                query.addCriteria(Criteria.where("activityId").in(activityIds));
            }
        }
        if (StringUtils.isNotBlank(request.getType())) {
            query.addCriteria(Criteria.where("type").is(request.getType()));
        }
        query.addCriteria(Criteria.where("deleted").ne(true));
        long count = mongoTemplate.count(query, ActivityStatistics.class);
        PageRequest pageRequest = PageRequest.of(request.getPage() - 1, request.getPageSize());
//        query.with(new Sort(Sort.Direction.DESC, "createdTime"));
        Sort sort = Sort.by(Sort.Direction.DESC, "priority", "updatedTime");

        query.with(sort);
        List<ActivityStatistics> datas = mongoTemplate.find(query.with(pageRequest), ActivityStatistics.class);
        for (ActivityStatistics a : datas) {
            Long c = userParticipateActivityInfoService.getJoinedCount(a.getActivityId());
            a.setJoinedNum(c.intValue());
            // 设置转化率
            this.setConversionRatio(a);
            // 设置退款比例
            this.setRefundRatio(a);
            // 设置客单价
            this.setPricePerCustomer(a);
            Double cost = activityCostStatisticsService.getTotalCost(a.getId());
            a.setTotalCost(cost);
            if (Objects.nonNull(a.getGmv())) {
                a.setGmv(a.getGmv() / 100D);
            }
            if (Objects.nonNull(a.getRefundGmv())) {
                Double d = getDouble(a.getRefundGmv(), 2);
                a.setRefundGmv(d);
            }
            Long joinedCount = userParticipateActivityInfoService.getJoinedCount(a.getActivityId());
            if (Objects.nonNull(joinedCount) && Objects.nonNull(a.getOrderNum())) {
                Integer joinedNum = a.getUserSignUpCount();
                if (joinedNum == 0) {
                    joinedNum = joinedCount.intValue();
                }
                Double r = Double.valueOf(a.getOrderNum()) * 100 / Double.valueOf(joinedNum);
                r = getDouble(r, 2);
                a.setConversionRatio(r);
            }
            setRefundRatio(a);
        }
        for (ActivityStatistics a : datas) {
            if (StringUtils.isBlank(a.getActivityId())) {
                continue;
            }
            this.simulationStData(a.getActivityId(), a);
        }
        return PageableExecutionUtils.getPage(datas, pageRequest, () -> count);
    }

    @Override
    public ActivityStatistics findOne(String id, String userName) {
        log.info(":>>> 开始获取活动统计:{}", id);
        Query query = new Query().addCriteria(Criteria.where("id").is(id));
        ActivityStatistics data = mongoTemplate.findOne(query, ActivityStatistics.class);
        if (Objects.nonNull(data)) {
            ActivitySimulationData a = activitySimulationDataService.findByActivityId(data.getActivityId());
            boolean in = platformConfigService.inSuperAccount(userName);
            if (in) {
                Double cost = activityCostStatisticsService.getTotalCost(id);
                data.setTotalCost(cost);
                // 设置毛利率
                this.setGrossMargin(data);
            }

            if (Objects.nonNull(data.getGmv())) {
                data.setGmv(data.getGmv() / 100);
            }
            this.simulationStData(data.getActivityId(), data);
            // 设置转化率
            this.setConversionRatio(data);
            // 设置退款比例
            this.setRefundRatio(data);
            // 设置客单价
            this.setPricePerCustomer(data);
        }
        return data;
    }

    @Override
    public ActivityStatistics findByActivityId(String id) {
        log.info(":>>> 开始获取活动统计活动ID:{}", id);
        Query query = new Query().addCriteria(Criteria.where("activityId").is(id));
        ActivityStatistics data = mongoTemplate.findOne(query, ActivityStatistics.class);
        return data;
    }

    @Async
    @Override
    public void increActivityStatistics(String activityId, ActivityStatistics req) {
        log.info(":>>> 开始更新活动数据:{}", activityId);
        if (Objects.isNull(req) || StringUtils.isBlank(activityId)) {
            log.error(":>>> 统计数据为空:请求参数或活动参数为空");
            return;
        }
        try {
            ActivityStatistics activityStatistics = this.findByActivityId(activityId);
            if (Objects.isNull(activityStatistics)) {
                activityStatistics = new ActivityStatistics();
                activityStatistics.setId(null);
                activityStatistics.setActivityId(activityId);
                ActivityInfo activityInfo = activityService.findOne(activityId);
                if (Objects.isNull(activityInfo)) {
                    log.error(":>>> 活动:{} 不存在", activityId);
                    return;
                }
                activityStatistics.setActivityName(activityInfo.getName());
                activityStatistics.setCreatedTime(new Date());
                activityStatistics = mongoTemplate.insert(activityStatistics);
                log.info(":>>> 活动统计数据不存在新增:{}", activityId);
            }
            Query query = new Query().addCriteria(Criteria.where("id").is(activityStatistics.getId()));
            Update update = new Update();
            if (Objects.nonNull(req.getOrderNum())) {
                update.inc("orderNum", req.getOrderNum());
            }
            if (Objects.nonNull(req.getItemNum())) {
                update.inc("itemNum", req.getItemNum());
            }
            if (Objects.nonNull(req.getGmv())) {
                update.inc("gmv", req.getGmv());
            }
            if (Objects.nonNull(req.getRefundOrderNum())) {
                update.inc("refundOrderNum", req.getRefundOrderNum());
            }
            if (Objects.nonNull(req.getRefundItemNum())) {
                update.inc("refundItemNum", req.getRefundItemNum());
            }
            if (Objects.nonNull(req.getRefundGmv())) {
                update.inc("refundGmv", req.getRefundGmv());
            }
            if (Objects.nonNull(req.getPayItemNum())) {
                update.inc("payItemNum", req.getPayItemNum());
            }
            if (Objects.nonNull(req.getGiftItemNum())) {
                update.inc("giftItemNum", req.getGiftItemNum());
            }
            if (StringUtils.isNotBlank(req.getType())) {
                update.set("type", req.getType());

            }
            update.set("updatedTime", new Date());
            mongoTemplate.updateFirst(query, update, ActivityStatistics.class);
        } catch (Exception e) {
            log.error(":>>> 更新活动数据错误:{}", e);
            return;
        }

    }

    @Override
    public void initActivityStatisticsType() {
        log.info(":>>> 开始初始化 start ActivityStatisticsService.initActivityStatisticsType");
        Query query = new Query();
        List<ActivityStatistics> activityStatisticsList = this.mongoTemplate.find(query, ActivityStatistics.class);
        if (CollectionUtils.isEmpty(activityStatisticsList)) {
            log.info(":>>> 开始初始化 end ActivityStatisticsService.initActivityStatisticsType");
            return;
        }
        Date now = new Date();
        activityStatisticsList.forEach(activityStatistics -> {
            ActivityInfo activityInfo = activityService.findOne(activityStatistics.getActivityId());
            if (Objects.nonNull(activityInfo)) {
                Query query1 = new Query();
                query1.addCriteria(Criteria.where("id").is(activityStatistics.getId()));
                Update update = new Update();
                update.set("type", activityInfo.getType());
                update.set("updatedTime", now);
                this.mongoTemplate.updateFirst(query1, update, ActivityStatistics.class);
                log.info(":>>> 开始初始化  ActivityStatisticsService.initActivityStatisticsType 活动名称 ->{} type ->{}",
                        activityInfo.getName(), activityInfo.getType());
            }
        });
        activityStatisticsList.clear();
        log.info(":>>>已结束 ActivityStatisticsService.initActivityStatisticsType");
    }


    @Override
    public void updateUserSignUpCount(String id, Integer userSignUpCount) {
        log.info(":>>> 【活动收款统计】更新报名人数 id:{} | userSignUpCount->{}", id, userSignUpCount);
        if (StringUtils.isBlank(id) || Objects.isNull(userSignUpCount) || userSignUpCount < 0) {
            return;
        }
        Query query = new Query();
        query.addCriteria(Criteria.where("id").is(id));
        Update update = new Update();
        update.set("userSignUpCount", userSignUpCount);
        update.set("updatedTime", new Date());
        this.mongoTemplate.updateFirst(query, update, ActivityStatistics.class);
    }

    /**
     * 保留几位小数
     *
     * @param f
     * @param n
     * @return
     */
    private Double getDouble(Double f, Integer n) {
        log.info(":>>> 获取double类型:{},{}", f, n);
        if (Double.isInfinite(f) || Double.isNaN(f)) {
            return 0.0D;
        }
        BigDecimal b = new BigDecimal(f);
        double f1 = b.setScale(n, BigDecimal.ROUND_HALF_UP).doubleValue();
        return f1;
    }

    private void setConversionRatio(ActivityStatistics a) {
        Integer joinedNum = a.getUserSignUpCount();
        if (joinedNum == 0) {
            joinedNum = a.getJoinedNum();
        }
        if (Objects.nonNull(joinedNum) && Objects.nonNull(a.getOrderNum())) {
            if (a.getOrderNum().intValue() < 1) {
                a.setConversionRatio(0.0D);
            } else {
                Double d = Double.valueOf(a.getOrderNum()) / Double.valueOf(joinedNum);
                d = getDouble(d, 4);
                a.setConversionRatio(d * 100);
            }
        }
    }

    private void setRefundRatio(ActivityStatistics a) {
        if (Objects.nonNull(a.getRefundOrderNum()) && Objects.nonNull(a.getOrderNum())) {
            if (a.getOrderNum().intValue() < 1) {
                a.setRefundRatio(0.0D);
            } else {
                Double d = Double.valueOf(a.getRefundOrderNum()) / Double.valueOf(a.getOrderNum());
                d = getDouble(d, 4);
                a.setRefundRatio(d * 100);
            }
        }
    }

    private void setPricePerCustomer(ActivityStatistics a) {
        if (Objects.nonNull(a.getGmv()) && Objects.nonNull(a.getOrderNum())) {
            if (a.getOrderNum().intValue() < 1) {
                a.setConversionRatio(0.0D);
            } else {
                Double d = Double.valueOf(a.getGmv()) / Double.valueOf(a.getOrderNum());
                d = getDouble(d, 4);
                a.setPricePerCustomer(d * 100);
            }
        }
    }

    /**
     * 设置毛利率
     *
     * @param a
     */
    private void setGrossMargin(ActivityStatistics a) {
        if (Objects.nonNull(a.getGmv()) && Objects.nonNull(a.getTotalCost())) {
            if (a.getGmv().intValue() < 1) {
                a.setGrossMargin(0.0D);
            } else {
                Double d = a.getGmv() - a.getTotalCost() / a.getGmv();
                d = getDouble(d, 4);
                a.setPricePerCustomer(d * 100);
            }
        }
    }

    /**
     * 获取Double 类型，保留两位小数
     *
     * @param d
     * @return
     */
    private Double getDouble(double d) {
        BigDecimal bg = new BigDecimal(d);
        double f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        return f1;
    }

    private void simulationStData(String activityId, ActivityStatistics data) {
        if (Objects.isNull(data) || StringUtils.isBlank(activityId)) {
            return;
        }
        ActivitySimulationData a = activitySimulationDataService.findByActivityId(activityId);
        if (Objects.isNull(a) || Objects.isNull(a.getGmvCoefficient())) {
            return;
        }
        if (Objects.nonNull(data.getGmv())) {
            data.setGmv(this.getDouble(data.getGmv() * a.getGmvCoefficient()));
        }
        if (Objects.nonNull(data.getOrderNum())) {
            Double orderNu = data.getOrderNum() * a.getGmvCoefficient();
            data.setOrderNum(orderNu.intValue());
        }
        if (Objects.nonNull(data.getItemNum())) {
            Double itemNum = data.getItemNum() * a.getGmvCoefficient();
            data.setItemNum(itemNum.intValue());
        }
        if (Objects.nonNull(data.getRefundOrderNum())) {
            Double refundOrderNum = data.getRefundOrderNum() * a.getGmvCoefficient();
            data.setRefundOrderNum(refundOrderNum.intValue());
        }
        if (Objects.nonNull(data.getRefundItemNum())) {
            Double refundItemNum = data.getRefundItemNum() * a.getGmvCoefficient();
            data.setRefundItemNum(refundItemNum.intValue());
        }
        if (Objects.nonNull(data.getRefundGmv())) {
            data.setRefundGmv(this.getDouble(data.getRefundGmv() * a.getGmvCoefficient()));
        }
        if (Objects.nonNull(data.getPayItemNum())) {
            Double payItemNum = data.getPayItemNum() * a.getGmvCoefficient();
            data.setPayItemNum(payItemNum.intValue());
        }
        if (Objects.nonNull(data.getGiftItemNum())) {
            Double giftItemNum = data.getGiftItemNum() * a.getGmvCoefficient();
            data.setGiftItemNum(giftItemNum.intValue());
        }

    }

}
